package com.openarena.model.dao;

import com.openarena.model.Game;
import com.openarena.model.GameKill;
import com.openarena.model.Player;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

public class GameDAO extends InfArenaDAO {

    private static final Logger logger = Logger.getLogger(GameDAO.class.getCanonicalName());

    public GameDAO() {
        super();
    }

    public Game getGameById(Integer id) {
        Session session = null;
        try {
            session = getSession();
            Game game = (Game) session.createCriteria(Game.class).add(Restrictions.eq("id", id)).uniqueResult();
            initGame(game);
            return game;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "", e);
            return null;
        } finally {
            close(session);
        }
    }

    public List<Game> getGamesSinceDate(Date date) {
        Session session = null;
        try {
            session = getSession();
            List<Game> games = session.createCriteria(Game.class).add(Restrictions.gt("playedDate", date))
                    .addOrder(Order.asc("playedDate")).list();
            initGames(games);
            return games;
        } catch (Exception e) {
            logger.log(Level.SEVERE, null, e);
            return Collections.EMPTY_LIST;
        } finally {
            close(session);
        }
    }

    public Game getLastGame() {
        Session session = null;
        try {
            session = getSession();

            Game game = (Game) session.createCriteria(Game.class).addOrder(Order.desc("playedDate")).setMaxResults(1).uniqueResult();
            initGame(game);
            return game;

        } catch (Exception e) {
            logger.log(Level.SEVERE, null, e);
            return null;
        } finally {
            close(session);
        }
    }

    public boolean existGameBeforeDate(Date playedDate) {
        Session session = null;
        try {
            session = getSession();
            return ((Integer) session.createCriteria(Game.class).add(Restrictions.lt("playedDate", playedDate)).setProjection(Projections.rowCount()).uniqueResult()) > 0;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "", e);
            return false;
        } finally {
            close(session);
        }
    }

    public boolean existGameAfterDate(Date playedDate) {
        Session session = null;
        try {
            session = getSession();
            return ((Integer) session.createCriteria(Game.class).add(Restrictions.gt("playedDate", playedDate)).setProjection(Projections.rowCount()).uniqueResult()) > 0;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "", e);
            return false;
        } finally {
            close(session);
        }
    }

    public Game getPreviousGame(Game game) {
        Session session = null;
        try {
            session = getSession();
            Game previousGame = (Game) session
                    .createCriteria(Game.class)
                    .add(Restrictions.lt("playedDate", game.getPlayedDate()))
                    .addOrder(Order.desc("playedDate"))
                    .setMaxResults(1)
                    .uniqueResult();

            initGame(previousGame);

            return previousGame;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "", e);
            return null;
        } finally {
            close(session);
        }
    }

    public Game getNextGame(Game game) {
        Session session = null;
        try {
            session = getSession();
            Game nextGame = (Game) session
                    .createCriteria(Game.class)
                    .add(Restrictions.gt("playedDate", game.getPlayedDate()))
                    .addOrder(Order.asc("playedDate"))
                    .setMaxResults(1)
                    .uniqueResult();

            initGame(nextGame);

            return nextGame;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "", e);
            return null;
        } finally {
            close(session);
        }
    }

    private void initGame(Game game) {
        if (game != null) {
            game.getStats().size();
        }
    }

    private void initGames(Collection<Game> games) {
        if (games != null) {
            for (Game game : games) {
                initGame(game);
            }
        }
    }
}
